package com.lechi.web.util;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.lechi.iot.netty.channel.ITcpChannel;
import com.lechi.web.common.utils.StringUtils;
import com.lechi.web.common.utils.spring.SpringUtils;
import com.lechi.web.constants.AppCmdConstants;
import com.lechi.web.constants.Constants;
import com.lechi.web.job.UploadSensorDataJob;
import com.lechi.web.service.IIotDeviceService;
import com.lechi.web.service.IIotMonitorDataService;
import com.lechi.web.service.impl.IotDeviceCommond;
import com.lechi.web.system.domain.IotDeviceBo;
import com.lechi.web.system.domain.IotMonitorDataBo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 高效缓存，针对没有并发写的操作
 */
@Slf4j
public class LeChiCacheUtil {

    public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);

    @Getter
    private final static Map<String, ITcpChannel> tcpChannelMap = Maps.newConcurrentMap();

    @Getter
    private final static Map<String, Date> offlineMap = Maps.newConcurrentMap();


    @Getter
    private final static Map<String, Boolean> offlineFlag = Maps.newConcurrentMap();

    public static String ifTimeOut(String deviceIdOrSN, int timeInternal) {
        String state = Optional.ofNullable(offlineMap.get(deviceIdOrSN))
                .filter(endTime -> new Date().getTime() - endTime.getTime() <= timeInternal * 60000L)
                .map(endTime -> AppCmdConstants.STARTED).orElse(AppCmdConstants.STOPED);
        return state;
    }


    /**
     * 更新Android设备离线状态
     */
    public static void androidOfflineLogTask() {
        scheduler.scheduleAtFixedRate(() -> {
            IotDeviceBo iotDeviceBo = new IotDeviceBo();
            iotDeviceBo.setProtocolType(String.format("'%s'", Constants.ANDROID_TCP));
            List<IotDeviceBo> list = SpringUtils.getBean(IIotDeviceService.class).selectIotDeviceList(iotDeviceBo);
            list.forEach(androidDevice -> {
                String state = ifTimeOut(androidDevice.getDeviceSn(), androidDevice.getTimeInterval());
                log.error("Android设备{}，是否在线标记：{} false 表示未离线", androidDevice.getDeviceSn(), offlineFlag.get(androidDevice.getDeviceSn()));
                if (AppCmdConstants.STOPED.equals(state) && !offlineFlag.get(androidDevice.getDeviceSn())) {
                    offlineFlag.put(androidDevice.getDeviceSn(), Boolean.TRUE);
                    Date date = offlineMap.getOrDefault(androidDevice.getDeviceSn(), new Date());
                    IotDeviceCommond.commond(androidDevice.getDeviceSn(), AppCmdConstants.STOPED, date);
                }
            });
        }, 60, 300, TimeUnit.SECONDS);
    }

    public static void lc001(String station, String date, int start, int mins, String type) {
        scheduler.scheduleAtFixedRate(() -> {
            IotMonitorDataBo iotMonitorDataBo = new IotMonitorDataBo();
            List<Long> longs = UploadSensorDataJob.sensorsMap.get(station + "_" + type);
            iotMonitorDataBo.setQualityCode(StringUtils.join(longs, ","));
            iotMonitorDataBo.setTableName(date);

            LocalDateTime startTime = LocalDateTime.of(2025, 7, start, 0, 0, 0);
            LocalDateTime endTime = LocalDateTime.of(2025, 7, start + 1, 12, 0, 0);
//            while (startTime.isBefore(endTime)) {
//                LocalDateTime currentEnd = startTime.plusMinutes(mins);
//                if (currentEnd.isAfter(endTime)) {
//                    currentEnd = endTime;
//                }
                iotMonitorDataBo.setParams(Map.of("beginTime", startTime.toString(), "endTime", endTime.toString()));
                final String fileName = StringUtils.format("{}_{}_{}.{}",station, endTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) , type, "json");
                Path path = Paths.get("D:/home/ftpfile/ftp/LC001/0" + start + "/", fileName);
                log.error("{}文件========={}", fileName, iotMonitorDataBo.getParams());
                List<IotMonitorDataBo> list = SpringUtils.getBean(IIotMonitorDataService.class).selectIotMonitorDataList(iotMonitorDataBo);
                List<JSONObject> jsonObjectList = new ArrayList<>();
                longs.forEach(sensorAliasId -> {
                    for (IotMonitorDataBo monitorDataBo : list) {
                        if (sensorAliasId.longValue() == monitorDataBo.getSensorAliasId().longValue()) {
                            JSONObject target = new JSONObject();
                            target.put("sensorId", monitorDataBo.getSensorAliasId());
                            target.put("val", monitorDataBo.getDoubleValue());
                            target.put("unit", monitorDataBo.getUnit());
                            String sensorAliasName = UploadSensorDataJob.map.get(station + "_" + monitorDataBo.getSensorAliasId());
                            target.put("name", Objects.isNull(sensorAliasName) ? monitorDataBo.getSensorAliasName() : sensorAliasName);
                            jsonObjectList.add(target);
                            break;
                        }
                    }
                });
                try {

                    Path dirPath = path.getParent();
                    if (dirPath != null) {
                        Files.createDirectories(dirPath);
                    }
                    StandardOpenOption[] options = Files.exists(path)
                            ? new StandardOpenOption[]{StandardOpenOption.APPEND}
                            : new StandardOpenOption[]{StandardOpenOption.CREATE, StandardOpenOption.APPEND};
                    int length = jsonObjectList.toString().length();
                    Files.write(path, (jsonObjectList.toString().substring(1,  length - 1)).getBytes(), options);
                } catch (IOException e) {
                    log.error("写入传感器数据产生异常!", e);
                }
//                startTime = currentEnd;
//            }
        }, 10, 277780, TimeUnit.SECONDS);
    }

}
